using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using WolfCarol.AvgToolkit.Command;
using WolfCarol.AvgToolkit.Save;

namespace WolfCarol.AvgToolkit.Examples
{
    public class VariableData
    {
        public KeyValuePair<string, string>[] StringDict;

        public KeyValuePair<string, float>[] FloatDict;

        public KeyValuePair<string, bool>[] BoolDict;

        public VariableData()
        {
            StringDict = new KeyValuePair<string, string>[0];
            FloatDict = new KeyValuePair<string, float>[0];
            BoolDict = new KeyValuePair<string, bool>[0];
        }
    }

    public class VariableManager : MonoBehaviour, ISavable<VariableData>
    {
        private Dictionary<string, string> m_stringDict = new();

        private Dictionary<string, float> m_floatDict = new();

        private Dictionary<string, bool> m_boolDict = new();

        public CommandManager commandManager;

        public void Clear()
        {
            m_stringDict.Clear();
            m_floatDict.Clear();
            m_boolDict.Clear();
        }

        public VariableData Save()
        {
            return new VariableData()
            {
                StringDict = m_stringDict.ToArray(),
                FloatDict = m_floatDict.ToArray(),
                BoolDict = m_boolDict.ToArray()
            };
        }

        public void Load(VariableData obj)
        {
            m_stringDict = new Dictionary<string, string>(obj.StringDict);
            m_floatDict = new Dictionary<string, float>(obj.FloatDict);
            m_boolDict = new Dictionary<string, bool>(obj.BoolDict);
        }

        public string GetString(string key)
        {
            return m_stringDict[key];
        }

        [Command("set_string", ExecutionOrders.Sequence)]
        public void SetString(string key, string value)
        {
            m_stringDict[key] = value;
        }

        [Command("set_float", ExecutionOrders.Sequence)]
        public void SetFloat(string key, float value)
        {
            m_floatDict[key] = value;
        }

        [Command("set_bool", ExecutionOrders.Sequence)]
        public void SetBool(string key, bool value)
        {
            m_boolDict[key] = value;
        }

        [Command("goto_if_float_cond", ExecutionOrders.Sequence)]
        public void GotoIfFloat(string key, char op, float value, string flag)
        {
            if ((op == '=' && m_floatDict[key] == value)
             || (op == '>' && m_floatDict[key] > value)
             || (op == '<' && m_floatDict[key] < value))
            {
                commandManager.Goto(flag);
            }
        }

        [Command("goto_if_string_cond", ExecutionOrders.Sequence)]
        public void GotoIfString(string key, string value, string flag)
        {
            if (m_stringDict[key] == value)
            {
                commandManager.Goto(flag);
            }
        }

        [Command("goto_if_bool_cond", ExecutionOrders.Sequence)]
        public void GotoIfBool(string key, char op, bool value, string flag)
        {
            if ((op == '=' && m_boolDict[key] == value)
             || op == '!' && m_boolDict[key] != value)
            {
                commandManager.Goto(flag);
            }
        }

        [Command("compute_float", ExecutionOrders.Sequence)]
        public void ComputeFloat(string key, char op, float value)
        {
            if (op == '+')
            {
                m_floatDict[key] += value;
            }
            else if (op == '-')
            {
                m_floatDict[key] -= value;
            }
            else if (op == '*')
            {
                m_floatDict[key] *= value;
            }
            else if (op == '/')
            {
                m_floatDict[key] /= value;
            }
        }
    }
}
